/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021.
 * Description: support net kbox feature
 * Author: kechengsong <kechengsong@huawei.com>
 * Create: 2021-05-24
 */

#include <linux/set_kbox_region.h>
#include <linux/rtos_sysctl.h>
#include <net/net_kbox.h>

#define MAX_UINT (~0U)
#define MAX_LOG_SIZE	(MAX_UINT / 1024)

int net_kbox_region_id;
unsigned int net_kbox_region_size;

int get_net_kbox_id(void)
{
	return net_kbox_region_id;
}

static int proc_net_kbox_region_size(struct ctl_table *table, int write,
				void __user *buffer,
				size_t *lenp, loff_t *ppos)
{
	int tmpid, ret;
	unsigned int pre_size, region_size;

	if (!write)
		return proc_dointvec_minmax(table, write, buffer, lenp, ppos);

	pre_size = net_kbox_region_size;

	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
	if (ret)
		return ret;

	if (net_kbox_region_size == 0) {
		net_kbox_region_size = pre_size;
		return -EINVAL;
	}

	if (net_kbox_region_size > MAX_LOG_SIZE) {
		net_kbox_region_size = pre_size;
		pr_err("net_kbox_region_size is too large!\n");
		return -EINVAL;
	}

	region_size = net_kbox_region_size * 1024;
	tmpid = kern_kbox_register_region("net_kbox", region_size, NULL);
	if (tmpid < 0) {
		net_kbox_region_size = pre_size;
		pr_err("register net kbox region failed with %d!\n", tmpid);
		return tmpid;
	}

	net_kbox_region_id = tmpid;
	return 0;
}

static struct ctl_table rtos_net_kbox_sysctls[] = {
	{
		.procname	= "net_kbox_region_size",
		.data		= &net_kbox_region_size,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0640,
		.proc_handler	= proc_net_kbox_region_size,
		.extra1		= SYSCTL_ZERO,
	},
	{}
};

rtos_kernel_sysctls_proc_init(rtos_net_kbox, rtos_net_kbox_sysctls);
